package com.liu.stockmarket.utils

import com.liu.stockmarket.model.ResponseResult
import com.liu.stockmarket.model.HoldingStockProfit
import com.liu.stockmarket.model.Stock
import com.liu.stockmarket.model.StockDetailAndProfit
import com.liu.stockmarket.repository.database.TransactionRecordRepository
import com.liu.stockmarket.repository.database.entity.StockEntity
import com.liu.stockmarket.repository.database.entity.TransactionRecordEntity
import com.liu.stockmarket.repository.network.EasyMoneyRepository
import com.liu.stockmarket.ui.self.SelfAdapter
import com.liu.stockmarket.ui.stock.HoldingStockAdapter
import org.apache.commons.lang3.StringUtils
import java.math.BigDecimal
import java.time.LocalDate
import java.time.LocalDateTime

class StockTransactionUtil {
    companion object {


        /**
         * @param compositeIndexSecids 指数代码（上证：1.000001,沪深300：1.000300,深证指数：0.399001,创业板指：0.399006）
         *  如：1.000001,1.000300,0.399001,0.399006
         */
        suspend fun nowPrice(
            easyMoneyRepository: EasyMoneyRepository,
            selfStocks: List<StockEntity>,
            compositeIndexSecids: String
        ): List<SelfAdapter.Item> {
            val funds = selfStocks.filter {
                it.stockType == Stock.StockType.FUND
            }
            val stocks = selfStocks.filter {
                it.stockType != Stock.StockType.FUND
            }
            val nowPrice = mutableListOf<SelfAdapter.Item>()

            if (!funds.isNullOrEmpty()) {
                val data = easyMoneyRepository.getFundTransactionInfo(funds.toFundCodes())
                if (!(data == null || !data.Success || data.TotalCount == 0)) {
                    nowPrice.addAll(data.Datas.toStockTransactionInfo()
                        .map {
                            toSelfAdapterItem(funds, it)
                        })
                }
            }
            if (!stocks.isNullOrEmpty()||StringUtils.isNoneBlank(compositeIndexSecids)) {
                val data = easyMoneyRepository.getStockTransactionInfo(
                    StringUtils.join(listOf(stocks.toStockSecids(), compositeIndexSecids), ",")
                )
                if (!(data?.data == null || data.data.total == 0)) {
                    nowPrice.addAll(data.data.diff.diffToStockTransaction()
                        .map {
                            toSelfAdapterItem(stocks, it)
                        })

                }
            }
            return nowPrice.toList()
        }

        private fun toSelfAdapterItem(
            funds: List<StockEntity>,
            it: HoldingStockProfit.StockTransactionInfo
        ): SelfAdapter.Item {
            val find = funds.find { f ->
                f.code == it.code
            }
            return SelfAdapter.Item(
                find?.id,
                it.code,
                name = it.name,
                type = find?.transactionExchange,
                stockType = find?.stockType,
                nowPrice =
                it.nowPrice,
                upOrDownMoney = it.upOrDownMoney,
                upOrDownPercent = it.upOrDownPercent
            )
        }

        /**
         * 股票 / 转债
         */
        suspend fun stock(
            easyMoneyRepository: EasyMoneyRepository,
            transactionRecordRepository: TransactionRecordRepository,
            holdingStock: List<StockEntity>?
        ): ResponseResult<HoldingStockProfit> {
            if (holdingStock.isNullOrEmpty()) {
                return ResponseResult.error("没有股票数据")
            }
            val data =
                easyMoneyRepository.getStockTransactionInfo(holdingStock.toStockSecids())

            return if (data?.data == null || data.data.total == 0) {
                ResponseResult.error("没有股票交易数据")
            } else {
                val todayRecord =
                    transactionRecordRepository.queryTodayTransactionRecord(LocalDate.now())
                parseHoldingStockTransaction(
                    holdingStock = holdingStock,
                    data.data.diff.diffToStockTransaction(),
                    todayRecord
                )
            }
        }

        /**
         * 基金
         */
        suspend fun fund(
            easyMoneyRepository: EasyMoneyRepository,
            transactionRecordRepository: TransactionRecordRepository,
            funds: List<StockEntity>?
        ): ResponseResult<HoldingStockProfit> {
            if (funds.isNullOrEmpty()) {
                return ResponseResult.error("没有基金数据")
            }

            val data = easyMoneyRepository.getFundTransactionInfo(funds.toFundCodes())
            return if (data == null || !data.Success || data.TotalCount == 0) {
                ResponseResult.error("没有基金交易数据")
            } else {
                val todayRecord =
                    transactionRecordRepository.queryTodayTransactionRecord(LocalDate.now())
                parseHoldingStockTransaction(
                    funds,
                    data.Datas.toStockTransactionInfo(),
                    todayRecord
                )
            }
        }

        /**
         * 多个
         */
        private fun parseHoldingStockTransaction(
            holdingStock: List<StockEntity>,
            stockTransactionInfo: List<HoldingStockProfit.StockTransactionInfo>,
            todayRecords: List<TransactionRecordEntity>
        ): ResponseResult<HoldingStockProfit> {
            if (stockTransactionInfo.isEmpty()) {
                return ResponseResult.error("没有股票交易数据")

            }

            val diff = stockTransactionInfo

            val list = holdingStock

            if (list.isNullOrEmpty()) {
                return ResponseResult.error("尚未添加股票数据")

            }


            val adapterDatas = // 该股票的今日交易数据
                list.mapNotNull {
                    val find = diff.find { d ->
                        d.code == it.code
                    }

                    // 该股票的今日交易数据
                    val todayRecord = todayRecords.filter { r ->
                        r.stockId == it.id
                    }


                    if (find == null) {
                        null
                    } else {

                        val parseProfit = parseProfit(it, find, todayRecord)

                        val isShow = todayRecord.isNotEmpty() ||
                                it.holdingNumber.setScale(1,BigDecimal.ROUND_CEILING) != BigDecimal.ZERO.setScale(1,BigDecimal.ROUND_CEILING)

                        HoldingStockAdapter.Item(
                            it.id!!,
                            it.name,
                            it.code,
                            it.stockType,
                            it.transactionExchange,
                            it.holdingPrice,
                            it.holdingNumber,
                            find.nowPrice,
                            parseProfit.holdingMoney,
                            parseProfit.todayProfit,
                            parseProfit.todayProfitPercent,
                            parseProfit.allProfit,
                            parseProfit.allProfitPercent,
                            parseProfit.dividends,
                            isShow,
                        )
                    }


                }

            // 总持有金额 要减去已经清仓的
            val allHoldingMoney = adapterDatas.filter {
                it.holdingNumber != BigDecimal.ZERO
            }.sumOf {
                it.holdingMoney
            }.setScale(5, BigDecimal.ROUND_HALF_UP)

            // 今日总盈亏
            val todayAllProfit = adapterDatas.sumOf {
                it.todayProfit
            }.setScale(5, BigDecimal.ROUND_HALF_UP)

            // 今日总盈亏率 = 今日收益金额 / （ 持仓金额 - 今日收益金额 ）
            val todayAllProfitPercent = if (todayAllProfit == BigDecimal.ZERO.setScale(5)) {
                BigDecimal.ZERO
            } else {
                (todayAllProfit / (allHoldingMoney - todayAllProfit)) * BigDecimal("100").setScale(5)
            }

            // 持有总盈亏  = 持有总收益金额 / （ 持仓金额 - 总收益金额 ）
            val allProfit = adapterDatas.filter {
                it.holdingNumber != BigDecimal.ZERO
            }.sumOf {
                it.allProfit
            }.setScale(5, BigDecimal.ROUND_HALF_UP)

            // 累计总盈亏
            val accumulativeProfit = adapterDatas.sumOf {
                it.allProfit
            }.setScale(5, BigDecimal.ROUND_HALF_UP)

            // 累计盈亏率
            val accumulativeProfitPercent =
                if (accumulativeProfit.setScale(5) == BigDecimal.ZERO.setScale(5)) {
                    BigDecimal.ZERO
                } else {
                    (accumulativeProfit / (adapterDatas.sumOf { it.holdingMoney } - accumulativeProfit)) * BigDecimal(
                        "100"
                    ).setScale(5, BigDecimal.ROUND_HALF_UP)
                }


            // 持有收益率
            val allProfitPercent = if (allProfit == BigDecimal.ZERO.setScale(5)) {
                BigDecimal.ZERO
            } else {
                (allProfit / (allHoldingMoney - allProfit)) * BigDecimal("100").setScale(5)
            }

            val header = HoldingStockProfit.Header(
                allHoldingMoney,
                todayAllProfit,
                todayAllProfitPercent,
                allProfit,
                allProfitPercent,
                accumulativeProfit,
                accumulativeProfitPercent = accumulativeProfitPercent
            )


            return ResponseResult.success(HoldingStockProfit(header, adapterDatas))
        }


        /**
         * 单个股票、基金、可转债
         */
        fun parseProfit(
            stock: StockEntity,
            transactionInfo: HoldingStockProfit.StockTransactionInfo,
            todayRecord: List<TransactionRecordEntity>? = null
        ): StockDetailAndProfit.Profit {
            // 是否是未上市的转债



            if (isNewBond(transactionInfo)) {
                return StockDetailAndProfit.Profit(
                    holdingMoney = stock.holdingPrice * stock.holdingNumber,
                    BigDecimal.ZERO,
                    BigDecimal.ZERO,
                    BigDecimal.ZERO,
                    BigDecimal.ZERO
                )
            }





            var todayProfitPercent: BigDecimal? = null
            var todayProfit: BigDecimal? = null


            // 持仓金额
            val holdingMoney = holdingMoney(stock, transactionInfo)

            // 持有收益
            val allProfit = calculateAllProfit(stock, transactionInfo)
            // 持有收益率
            val allProfitPercent = calculateAllProfitPercent(stock, transactionInfo)



            // todo 看看是否可行
            if (LocalDateTime.now().nonTradingHours() && stock.holdingNumber != BigDecimal.ZERO) {
                // 周末
                return StockDetailAndProfit.Profit(
                    holdingMoney =holdingMoney,
                    BigDecimal.ZERO,
                    BigDecimal.ZERO,
                    allProfit,
                    allProfitPercent
                )
            }




            // 今日的交易盈亏
            val todayTransactionProfit = todayRecord?.sumOf {
                when (it.transactionType) {
                    TransactionRecordEntity.TransactionType.BUY -> {
                        (transactionInfo.nowPrice - it.transactionPrice) * it.transactionNumber - it.handlingFee
                    }
                    TransactionRecordEntity.TransactionType.DIVIDENDS -> {
                        it.transactionNumber * it.transactionPrice
                    }
                    TransactionRecordEntity.TransactionType.SELL -> {
                        (it.transactionPrice - transactionInfo.yesterdayPrice) * it.transactionNumber - it.handlingFee
                    }
                }

            } ?: BigDecimal.ZERO

            val dividends:BigDecimal = todayRecord?.sumOf {
                when (it.transactionType) {
                    TransactionRecordEntity.TransactionType.DIVIDENDS -> {
                        it.transactionNumber * it.transactionPrice
                    }
                    else-> BigDecimal.ZERO

                }

            } ?: BigDecimal.ZERO


            //清仓
            if (stock.holdingNumber == BigDecimal.ZERO) {
                return StockDetailAndProfit.Profit(
                    holdingMoney = BigDecimal.ZERO,
                    todayProfit = todayTransactionProfit,
                    todayProfitPercent = BigDecimal.ZERO,
                    allProfit = stock.holdingPrice.negate(),
                    allProfitPercent = BigDecimal.ZERO,
                    dividends = dividends
                )
            }


            if (LocalDate.now().isSameDay(stock.firstTransactionDate)) {
                todayProfitPercent = allProfitPercent
                todayProfit = allProfit
            } else {



                // 今日盈亏
                todayProfit = todayProfit(stock, transactionInfo,todayRecord?.filter {
                    it.transactionType == TransactionRecordEntity.TransactionType.BUY
                }?.sumOf { it.transactionNumber }?: BigDecimal.ZERO) + todayTransactionProfit.setScale(5,BigDecimal.ROUND_CEILING)
                // 今日盈亏率

                todayProfitPercent =
                    if (todayTransactionProfit == BigDecimal.ZERO) transactionInfo.upOrDownPercent else {
                        (todayProfit.setScale(5,BigDecimal.ROUND_CEILING) / (holdingMoney  - todayProfit)) * BigDecimal(
                            "100"
                        ).setScale(5)
                    }
            }

            return StockDetailAndProfit.Profit(
                holdingMoney, todayProfit, todayProfitPercent, allProfit, allProfitPercent,dividends
            )

        }

        /**
         * 股票总盈亏
         */
        private fun calculateAllProfit(
            stock: StockEntity,
            diff: HoldingStockProfit.StockTransactionInfo
        ): BigDecimal {
            val number = stock.holdingNumber
            return number * (diff.nowPrice - stock.holdingPrice)
        }

        /**
         * 持有收益率 （当前价格 - 成本价持仓价） /  成本价持仓价
         */
        private fun calculateAllProfitPercent(
            stock: StockEntity,
            diff: HoldingStockProfit.StockTransactionInfo
        ): BigDecimal {
            if (stock.holdingPrice.setScale(5) == BigDecimal.ZERO.setScale(5)) {
                return BigDecimal.ZERO
            }
            return ((diff.nowPrice.setScale(5) - stock.holdingPrice.setScale(5))
                    / stock.holdingPrice.setScale(5)) * BigDecimal("100").setScale(5)

        }

        /**
         * 今日盈亏
         * @param todayNumber 今日交易的数量不参与计算
         */
        private fun todayProfit(
            stock: StockEntity,
            diff: HoldingStockProfit.StockTransactionInfo,
            todayNumber:BigDecimal
        ): BigDecimal {
            val number = stock.holdingNumber-todayNumber
            return number * diff.upOrDownMoney
        }

        /**
         * 股票持仓金额
         */
        private fun holdingMoney(
            stock: StockEntity,
            diff: HoldingStockProfit.StockTransactionInfo
        ): BigDecimal {

            return if (diff.nowPrice == BigDecimal.ZERO && diff.upOrDownPercent == BigDecimal.ZERO
                && diff.upOrDownMoney == BigDecimal.ZERO
            ) {
                // 停牌
                stock.holdingNumber * diff.yesterdayPrice
            } else {
                stock.holdingNumber * diff.nowPrice
            }.setScale(5, BigDecimal.ROUND_HALF_UP)

        }
    }
}